package com.lzx.applib.attacher;

import android.os.SystemClock;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewTreeObserver;

import com.lzx.applib.utils.LogUtil;
import com.lzx.applib.utils.PointUtil;

/**
 * Created by Administrator on 16/11/06.
 */

public class GestureAttacher extends GestureDetector.SimpleOnGestureListener implements ScaleGestureDetector.OnScaleGestureListener {

    private static final String TAG = "GestureAttacher";
    private static final int SCROLL_NONE = -2;
    private static final int SCROLL_WAIT = -1;
    private static final int SCROLL_V_LEFT = 0;
    private static final int SCROLL_V_RIGHT = 1;
    private static final int SCROLL_H = 2;

    private final GestureCallback callback;
    private int width;
    private int height;
    private int border;

    private float downX;
    private float downY;
    private float borderBeginX;
    private float borderBeginY;

    private float scale;

    private long longPressBeginTime = -1;
    private int scrollType = SCROLL_NONE;

    public static void attach(final View view, final GestureCallback callback) {
        view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                final GestureAttacher attacher = new GestureAttacher(view.getWidth(), view.getHeight(),callback);
                final GestureDetector detector = new GestureDetector(view.getContext(), attacher);
                final ScaleGestureDetector detector2 = new ScaleGestureDetector(view.getContext(), attacher);
                view.setOnTouchListener(new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        if (attacher.width ==0 || attacher.height == 0) {
                            attacher.setViewSize(view.getWidth(), view.getHeight());
                        }
                        detector.onTouchEvent(event);
                        detector2.onTouchEvent(event);
                        if (attacher.longPressBeginTime != -1) {
                            attacher.onLongPressTime(SystemClock.elapsedRealtime() - attacher.longPressBeginTime);
                        }
                        return true;
                    }
                });
                view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
    }

    public GestureAttacher(int width, int height, GestureCallback attacher) {
        LogUtil.d(TAG, "GestureAttacher() called with: width = [" + width + "], height = [" + height + "]");
        this.width = width;
        this.height = height;
        this.border = width/10;
        this.callback = attacher; 
    }

    public void setViewSize(int width, int height) {
        this.width = width;
        this.height = height;
        this.border = width/10;
    }

    @Override
    public final boolean onDown(MotionEvent e) {
        LogUtil.d(TAG, "onDown");
        downX = e.getX();
        downY = e.getY();

        scrollType = SCROLL_WAIT;
        longPressBeginTime = -1;
        return super.onDown(e);
    }

    @Override
    public final void onLongPress(MotionEvent e) {
        LogUtil.d(TAG, "onLongPress");
        longPressBeginTime = SystemClock.elapsedRealtime();
        onLongPressTime(0);
        super.onLongPress(e);
    }

    @Override
    public final boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        LogUtil.d(TAG, "onScroll");
        switch (scrollType) {
            case SCROLL_WAIT:
                initScrollType(e2);
                break;
            case SCROLL_H:
                onScrollHorizontal(distanceX, borderBeginX-e2.getX());
                break;
            case SCROLL_V_LEFT:
                onScrollVerticalLeft(distanceY, borderBeginY-e2.getY());
                break;
            case SCROLL_V_RIGHT:
                onScrollVerticalRight(distanceY, borderBeginY-e2.getY());
                break;
            case SCROLL_NONE:
                break;
        }
        return super.onScroll(e1, e2, distanceX, distanceY);
    }

    @Override
    public final boolean onDoubleTap(MotionEvent e) {
        LogUtil.d(TAG, "onDoubleTap");
        if (callback != null) {
            callback.onDoubleTap(e);
        }
        return super.onDoubleTap(e);
    }

    @Override
    public final boolean onSingleTapConfirmed(MotionEvent e) {
        LogUtil.d(TAG, "onSingleTapConfirmed");
        if (callback != null) {
            callback.onSingleTap(e);
        }
        return super.onSingleTapConfirmed(e);
    }

    @Override
    public final boolean onContextClick(MotionEvent e) {
        LogUtil.d(TAG, "onContextClick");
        return super.onContextClick(e);
    }

    private void initScrollType(MotionEvent e) {
        float dis = PointUtil.getDistance(downX, downY, e.getX(), e.getY());
        LogUtil.d(TAG, "initScrollType: ", dis, border);
        if (dis >= border) {
            float gradient = Math.abs(PointUtil.getGradient(downX, downY, e.getX(), e.getY()));
            if (1 > gradient) {
                scrollType = SCROLL_H;
            } else if (downX < width/4) {
                scrollType = SCROLL_V_LEFT;
            } else if (downX > width/4*3){
                scrollType = SCROLL_V_RIGHT;
            } else {
                scrollType = SCROLL_NONE;
            }
            LogUtil.d(TAG, "initScrollType: ", gradient, scrollType);
            borderBeginX = e.getX();
            borderBeginY = e.getY();
        }
    }

    public final void onScrollHorizontal(float disCur, float disAll) {
        LogUtil.d(TAG, "onScrollHorizontal", disCur, disAll);
        if (callback != null) {
            callback.onScrollHorizontal(disCur, disAll);
        }
    }

    public final void onScrollVerticalLeft(float disCur, float disAll) {
        LogUtil.d(TAG, "onScrollVerticalLeft", disCur, disAll);
        if (callback != null) {
            callback.onScrollVerticalLeft(disCur, disAll);
        }
    }
    public final void onScrollVerticalRight(float disCur, float disAll) {
        LogUtil.d(TAG, "onScrollVerticalRight", disCur, disAll);
        if (callback != null) {
            callback.onScrollVerticalRight(disCur, disAll);
        }
    }

    public final void onLongPressTime(long time) {
        LogUtil.d(TAG, "onLongPressTime", time);
        if (callback != null) {
            callback.onLongPress(time);
        }
    }

    @Override
    public final boolean onScale(ScaleGestureDetector detector) {
        scale *= detector.getScaleFactor();
        LogUtil.d(TAG, "onScale", detector.getScaleFactor(), scale);
        if (callback != null) {
            callback.onScale(detector.getScaleFactor(), scale);
        }
        return true;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        LogUtil.d(TAG, "onScaleBegin");
        scale = 1;
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        LogUtil.d(TAG, "onScaleEnd");
        scale = 1;
    }

    interface GestureCallback {
        public void onScrollHorizontal(float disCur, float disAll);
        public void onScrollVerticalLeft(float disCur, float disAll);
        public void onScrollVerticalRight(float disCur, float disAll);
        public void onSingleTap(MotionEvent event);
        public void onDoubleTap(MotionEvent event);
        public void onLongPress(long time);
        public void onScale(float scaleCur, float scaleAll);
    }

    public static class SimpleGestureCallback implements GestureCallback {

        @Override
        public void onScrollHorizontal(float disCur, float disAll) {

        }

        @Override
        public void onScrollVerticalLeft(float disCur, float disAll) {

        }

        @Override
        public void onScrollVerticalRight(float disCur, float disAll) {

        }

        @Override
        public void onSingleTap(MotionEvent event) {

        }

        @Override
        public void onDoubleTap(MotionEvent event) {

        }

        @Override
        public void onLongPress(long time) {

        }

        @Override
        public void onScale(float scaleCur, float scaleAll) {

        }
    }
}
